<?php
abstract class Users_Model_Abstract {
	/**
	 * Добавление условия по количеству получаемых элементов.
	 * 
	 * @param Zend_Db_Select $oSelect
	 * @param integer|array $mLimit
	 * @param string $sClassName
	 */
	protected static function _addLimit2DbSelect(Zend_Db_Select $oSelect,$mLimit,$sClassName = __CLASS__)
	{
		switch (TRUE)
		{
			// Отсутствие ограничения на количество получаемых записей.
			case empty($mLimit):
				break;

			// Ограничение на количество первых $mLimit записей.
			case is_integer($mLimit):
				$oSelect->limit($mLimit);
				break;

			// Обнаружен неправильный тип параметра.
			case !is_array($mLimit):
				$sMsg = sprintf(self::I18N_PARAM_MUST_BE_ARRAY,'$mLimit',"$sClassName::getList");
				throw new Core_Content_Exception($sMsg);

			// Выборка первых $mLimit[0] записей.
			case count($mLimit) == 1:
				$oSelect->limit($mLimit[0]);
				break;

			// Выборка $mLimit[0] записей начиная с позиции $mLimit[1].
			case count($mLimit) == 2:
				$oSelect->limit($mLimit[0],$mLimit[1]);
				break;

			// Выборка $mLimit[0] записей для страницы $mLimit[2] (возможно со смещением $mLimit[1]).
			case count($mLimit) == 3:
				$oSelect->limit($mLimit[0],$mLimit[1] + $mLimit[0] * $mLimit[2]);
				break;

			// Обнаруженно неправильное количество элементов в параметре $mLimit.
			default:
				$sMsg = sprintf(self::I18N_WRONG_PARAM,'$mLimit',"$sClassName::getList");
				throw new Core_Content_Exception($sMsg);
		}
	}

	/**
	 * Получение списка объектов.
	 * 
	 * @param Zend_Db_Table_Abstract $oTable
	 * @param array $aFilter
	 * @param array $aOrder
	 * @param mixed $mLimit
	 * @param callable $callbackFilter
	 * @param array $aSharedFilter
	 * @return Zend_Db_Select
	 */
	protected static function _getList($oTable,$aFilter,$aOrder,$mLimit,$callbackFilter,$aSharedFilter = array()) {
		$oSelect = $oTable->select();
		$aFilter = array_key_exists(0,$aFilter) ? $aFilter : array($aFilter);

		// Обработка подфильтров, объединяемых через "OR".
		foreach ($aFilter as $aSubFilter) {
			$bIsFirst = true;
			$aSubFilter = array_merge($aSubFilter,$aSharedFilter);

			// Обработка условий фильтрации, объединяемых через "AND".
			foreach ($aSubFilter as $sKey => $mValue) {
				// Парсим правила фильтрации.
				preg_match('~^([<>!]=?)(.*?)$~',$sKey,$aMatch);
				$sRule = $aMatch[1] ?( $aMatch[1][0] == '!' ? '<>' : $aMatch[1] ): '=';
				$sKey = $aMatch[2];

				// Вызываем метод-обработчик текущего фильтра.
				list($mCond,$mValue) = call_user_func($callbackFilter,$sKey,$sRule,$mValue);

				// Добавления условия фильтрации в объект Zend_Db_Table_Select.
				$bIsFirst ? $oSelect->orWhere($mCond,$mValue) : $oSelect->where($mCond,$mValue);
				$bIsFirst = false;
			}
		}

		// Обработка сортировки.
		foreach ($aOrder as $mKey => $sOrderRule) {
			if (is_integer($mKey)) {
				$oSelect->order($sOrderRule);
			}
			else {
				$oSelect->order("$mKey $sOrderRule");
			}
		}

		// Обработка ограничения количества возращаемых записей.
		self::_addLimit2DbSelect($oSelect,$mLimit,__CLASS__);

		return $oSelect;
	}
}
?>